#include "PocelainPrerequisites.h"
#include "TMathUtils.hpp"
#include "TVector.hpp"
#include <cmath>

POCELAIN_NAMESPACE_BEGIN
template <class T>
struct TSpherical
{
public:
    typedef T value_type;
    typedef TSpherical<T> type;
    typedef TVector<T, 3> vec_t;
    T theta;
    T phi;
    T radius;
    TSpherical(T radius = T(1),T phi = T(0),T theta = T(0) )
    {
        this->radius = radius;
        this->phi = phi; // polar angle
        this->theta = theta; // azimuthal angle
    }

    type& set(T radius,T phi,T theta )
    {
        this->radius = radius;
        this->phi = phi;
        this->theta = theta;
        return *this;
    }

    type& copy(const type& other )
    {
        this->radius = other.radius;
        this->phi = other.phi;
        this->theta = other.theta;
        return *this;
    }

    // restrict phi to be between EPS and PI-EPS
    type& makeSafe()
    {
        const T EPS = 0.000001;
        this->phi = std::max( EPS, std::min( TMathUtils<T>::PI - EPS, this->phi ) );
        return *this;
    }

    type& setFromVector3(const vec_t &v )
    {
        return this->setFromCartesianCoords( v.x, v.y, v.z );
    }

    type& setFromCartesianCoords(T x,T y,T z )
    {
        this->radius = std::sqrt( x * x + y * y + z * z );

        if ( this->radius == 0 )
        {
            this->theta = 0;
            this->phi = 0;
        }
        else
        {

            this->theta = std::atan2( x, z );
            this->phi = std::acos( TMathUtils<T>::clamp( y / this->radius, - 1, 1 ) );

        }

        return *this;

    }

    type &clone()
    {
        return *this;
    }

};

POCELAIN_NAMESPACE_END
